package org.emavaj.sanguosha.model.card.resource;

import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.log4j.Logger;
import org.emavaj.common.MathUtil;
import org.emavaj.common.ReflectUtil;
import org.emavaj.sanguosha.model.card.AbstractCard;
import org.emavaj.sanguosha.model.constants.Constants;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * User: DIZEM Time: 11-3-30 下午3:01
 * 
 * eMavaj updated 20120915
 */
public class Deck {

	private static Logger log = Logger.getLogger(Deck.class);

	private static Deck instance;

	// 当前牌堆
	private ArrayList<AbstractCard> deck;
	// 弃牌牌堆
	private ArrayList<AbstractCard> backDeck;
	// 顶部缓冲牌堆 用于诸葛亮占星
	private ArrayList<AbstractCard> topBufferDeck;
	// 底部缓冲牌堆 用于诸葛亮占星
	private ArrayList<AbstractCard> bottomBufferDeck;

//	private static final Map<String, CardResInfo> cardResInfo = new HashMap<String, CardResInfo>();

	// private Random random;

	private Deck() {
		deck = new ArrayList<AbstractCard>();
		backDeck = new ArrayList<AbstractCard>();
		topBufferDeck = new ArrayList<AbstractCard>();
		bottomBufferDeck = new ArrayList<AbstractCard>();
		// random = new Random();
	}

	public synchronized static Deck getInstance() {
		if (instance == null) {
			instance = new Deck();
			instance.init();
		}
		return instance;
	}

	public int getRemainSize() {
		return deck.size();
	}

	/**
	 * 从牌堆摸一张牌
	 * 
	 * @return
	 * @throws Exception
	 */
	public AbstractCard popCard() {
		if (!topBufferDeck.isEmpty())
			return topBufferDeck.remove(0);
		if (deck.size() == 0) {
			if (!bottomBufferDeck.isEmpty())
				return bottomBufferDeck.remove(0);
			refreshDeck();
		}
		System.out.println(deck.size());
		AbstractCard card = deck.remove(MathUtil.getRandomInt(deck.size()));
		return card;
	}

	/**
	 * 刷新牌堆，用于牌堆被摸完后
	 * 
	 * @return
	 */
	public boolean refreshDeck() {
		if (deck.size() == 0) {
			deck = backDeck;
			backDeck = new ArrayList<AbstractCard>();
			if (deck.size() != 0) {
				return true;
			} else {
				return false;
			}
		}
		return false;
	}

	public void addToBack(AbstractCard card) {
		backDeck.add(card);
	}

	public void addToTop(AbstractCard card) {
		topBufferDeck.add(card);
	}

	public void addToBottom(AbstractCard card) {
		bottomBufferDeck.add(card);
	}

	/**
	 * 读取牌配置
	 */
	private void init() {
		String CardXML = Constants.CARD_SETTING_PATH;
		int cnt = 0;
		try {
			String description = null;
			DocumentBuilder bf = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder();
			// 取得xml doc
			Document document = bf.parse(CardXML);
			// 取得<CardSettings>
			Node cardSettings = document.getChildNodes().item(0);
			// basic card, equipment card...
			NodeList nl = cardSettings.getChildNodes();
			final int nlCount = nl.getLength();
			for (int i = 0; i < nlCount; i++) {

				Node inode = nl.item(i);
				if (inode.getNodeType() != Node.ELEMENT_NODE) {
					continue;
				}
				// <BasicCard> or ...
				//String cardKind = inode.getNodeName();
				// type sha or shan or tao or ...
				NodeList typeList = inode.getChildNodes();
				final int typeCount = typeList.getLength();
				for (int j = 0; j < typeCount; j++) {
					// one kind of card
					Node jnode = typeList.item(j);
					if (jnode.getNodeType() != Node.ELEMENT_NODE) {
						continue;
					}
					// <desc> or <Card>
					NodeList cardList = jnode.getChildNodes();
					NamedNodeMap typeMap = jnode.getAttributes();

					final int cardCount = cardList.getLength();
					for (int k = 0; k < cardCount; k++) {
						// Node cardTag = cardList.item(k);
						Node card = cardList.item(k);
						if (card.getNodeType() != Node.ELEMENT_NODE) {
							continue;
						}

						// <description>
						if (card.getNodeName().equals("description")) {
							description = card.getFirstChild().getNodeValue();

						} else if (card.getNodeName().equals("Card")) { // <card>
							NamedNodeMap map = card.getAttributes();
							// if (!cardResInfo.containsKey(cardName)) {
							// cardResInfo.put(cardName,
							// new CardResInfo(cardName, )
							// .getNodeValue(), ));
							// }
							CardResHelper
									.addCardResInfo(typeMap
											.getNamedItem("type")
											.getNodeValue(), typeMap
											.getNamedItem("filename")
											.getNodeValue(), description);
							addToBack(getCard(typeMap, map));
							++cnt;
						}
					}
				}
			}
			log.info("Read " + cnt + " cards infomation from CardSetting.xml");

		} catch (Exception e) {
			log.error(e.getMessage());
		}
	}

	private AbstractCard getCard(NamedNodeMap typeMap, NamedNodeMap map) throws ClassNotFoundException,
			InstantiationException, IllegalAccessException {
		String cardCls = typeMap.getNamedItem("class").getNodeValue();
		AbstractCard card = (AbstractCard) ReflectUtil
				.getClassInstance(cardCls);
		card.init(typeMap, map);
		return card;
	}

	public static void main(String[] args) {
		System.out.println(Deck.getInstance().popCard());
	}
}
